package com.linq.cool.oauth.controller;

import com.alibaba.fastjson.JSONObject;
import com.linq.cool.common.core.utils.JsonUtils;
import com.linq.cool.oauth.config.AlipayOauthProperties;
import com.linq.cool.oauth.config.GiteeOauthProperties;
import com.linq.cool.oauth.config.GithubOauthProperties;
import com.linq.cool.oauth.config.WeiboOauthProperties;
import com.xkcoding.http.config.HttpConfig;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.enums.scope.*;
import me.zhyd.oauth.exception.AuthException;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.*;
import me.zhyd.oauth.utils.AuthScopeUtils;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.Arrays;

/**
 * @Author: yqlin
 * @Date: 2021/1/21 05:31
 * @Description:
 * @Version: 1.0.0
 */
@Slf4j
@RestController
public class OauthController {


    @GetMapping("render/{source}")
    public void renderAuth(@PathVariable("source") String source, HttpServletResponse response) throws IOException {
        log.info("进入renderAuth,来源 : {}", source);
        AuthRequest authRequest = getAuthRequest(source);
        String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
        log.info(authorizeUrl);
        response.sendRedirect(authorizeUrl);
    }


    @GetMapping("callback/{source}")
    public void login(@PathVariable("source") String source, AuthCallback callback) {
        log.info("进入callback：" + source + " callback params：" + JSONObject.toJSONString(callback));
        AuthRequest authRequest = getAuthRequest(source);
        AuthResponse<?> authResponse = authRequest.login(callback);
        log.info("{} 登录回调:{}", source, authResponse);
        // 处理逻辑
        if (authResponse.ok()) {
            AuthUser authUser = (AuthUser) authResponse.getData();
            log.info("{} 授权成功: {}", source, JsonUtils.printJson(authUser.getRawUserInfo()));
        } else {
            log.info("{} 授权失败,错误信息: {}", source, authResponse.getMsg());
        }
    }
    //
    //    @GetMapping("/revoke/{source}/{uuid}")
    //    public R<?> revokeAuth(@PathVariable("source") String source, @PathVariable("uuid") String uuid) throws IOException {
    //        AuthRequest authRequest = getAuthRequest(source.toLowerCase());
    //        AuthUser user = userService.getByUuid(uuid);
    //        if (null == user) {
    //            return R.fail("用户不存在");
    //        }
    //        AuthResponse<AuthToken> response = null;
    //        try {
    //            response = authRequest.revoke(user.getToken());
    //            if (response.ok()) {
    //                userService.remove(user.getUuid());
    //                return R.ok("用户 [" + user.getUsername() + "] 的 授权状态 已收回！");
    //            }
    //            return R.fail("用户 [" + user.getUsername() + "] 的 授权状态 收回失败！" + response.getMsg());
    //        } catch (AuthException e) {
    //            return R.fail(e.getErrorMsg());
    //        }
    //    }
//
//    @RequestMapping("/refresh/{source}/{uuid}")
//    @ResponseBody
//    public Object refreshAuth(@PathVariable("source") String source, @PathVariable("uuid") String uuid) {
//        AuthRequest authRequest = getAuthRequest(source.toLowerCase());
//
//        AuthUser user = userService.getByUuid(uuid);
//        if (null == user) {
//            return Response.error("用户不存在");
//        }
//        AuthResponse<AuthToken> response = null;
//        try {
//            response = authRequest.refresh(user.getToken());
//            if (response.ok()) {
//                user.setToken(response.getData());
//                userService.save(user);
//                return Response.success("用户 [" + user.getUsername() + "] 的 access token 已刷新！新的 accessToken: " + response.getData().getAccessToken());
//            }
//            return Response.error("用户 [" + user.getUsername() + "] 的 access token 刷新失败！" + response.getMsg());
//        } catch (AuthException e) {
//            return Response.error(e.getErrorMsg());
//        }
//    }


    /**
     * 根据具体的授权来源，获取授权请求工具类
     *
     * @param source 授权来源
     *
     * @return AuthRequest
     */
    private AuthRequest getAuthRequest(String source) {
        AuthRequest authRequest = null;
        switch (source.toLowerCase()) {
            case "alipay":
                authRequest = new AuthAlipayRequest(
                        AuthConfig
                                .builder()
                                .clientId(AlipayOauthProperties.ALIPAY_CLIENT_ID)
                                .clientSecret(AlipayOauthProperties.ALIPAY_CLIENT_SERECT)
                                .alipayPublicKey(AlipayOauthProperties.ALIPAY_PUBLIC_KEY)
                                .redirectUri(AlipayOauthProperties.ALIPAY_REDIRECT_URL)
                                .build());
                log.info("authRequest: {}", authRequest);
                break;
            case "gitee":
                // 支付宝在创建回调地址时，不允许使用localhost或者127.0.0.1，所以这儿的回调地址使用的局域网内的ip
                authRequest = new AuthGiteeRequest(
                        AuthConfig
                                .builder()
                                .clientId(GiteeOauthProperties.GITEE_CLIENT_ID)
                                .clientSecret(GiteeOauthProperties.GITEE_CLIENT_SERECT)
                                .redirectUri(GiteeOauthProperties.GITEE_REDIRECT_URL)
                                .scopes(AuthScopeUtils.getScopes(AuthGiteeScope.values()))
                                .build());
                break;
            case "github":
                authRequest = new AuthGithubRequest(AuthConfig.builder()
                                                            .clientId(GithubOauthProperties.GITHUB_CLIENT_ID)
                                                            .clientSecret(GithubOauthProperties.GITHUB_CLIENT_SERECT)
                                                            .redirectUri(GithubOauthProperties.GITHUB_REDIRECT_URL)
                                                            .scopes(AuthScopeUtils.getScopes(AuthGithubScope.values()))
                                                            // 针对国外平台配置代理
//                                                            .httpConfig(HttpConfig.builder()
//                                                                                .timeout(15000)
//                                                                                .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 10080)))
//                                                                                .build())
                                                            .build());
                break;
            case "weibo":
                authRequest = new AuthWeiboRequest(AuthConfig.builder()
                                                           .clientId(WeiboOauthProperties.WEIBO_CLIENT_ID)
                                                           .clientSecret(WeiboOauthProperties.WEIBO_CLIENT_SERECT)
                                                           .redirectUri(WeiboOauthProperties.WEIBO_REDIRECT_URL)
                                                           .scopes(Arrays.asList(
                                                                   AuthWeiboScope.EMAIL.getScope(),
                                                                   AuthWeiboScope.FRIENDSHIPS_GROUPS_READ.getScope(),
                                                                   AuthWeiboScope.STATUSES_TO_ME_READ.getScope()
                                                           )).build());
                break;
            case "dingtalk":
                authRequest = new AuthDingTalkRequest(AuthConfig.builder()
                                                              .clientId("")
                                                              .clientSecret("")
                                                              .redirectUri("http://localhost:8443/oauth/callback/dingtalk")
                                                              .build());
                break;
            case "baidu":
                authRequest = new AuthBaiduRequest(AuthConfig.builder()
                                                           .clientId("")
                                                           .clientSecret("")
                                                           .redirectUri("http://localhost:8443/oauth/callback/baidu")
                                                           .scopes(Arrays.asList(
                                                                   AuthBaiduScope.BASIC.getScope(),
                                                                   AuthBaiduScope.SUPER_MSG.getScope(),
                                                                   AuthBaiduScope.NETDISK.getScope()
                                                           ))
//                        .clientId("")
//                        .clientSecret("")
//                        .redirectUri("http://localhost:9001/oauth/baidu/callback")
                                                           .build());
                break;
            case "coding":
                authRequest = new AuthCodingRequest(AuthConfig.builder()
                                                            .clientId("")
                                                            .clientSecret("")
                                                            .redirectUri("http://dblog-web.zhyd.me/oauth/callback/coding")
                                                            .codingGroupName("")
                                                            .scopes(Arrays.asList(
                                                                    AuthCodingScope.USER.getScope(),
                                                                    AuthCodingScope.USER_EMAIL.getScope(),
                                                                    AuthCodingScope.USER_PHONE.getScope()
                                                            ))
                                                            .build());
                break;
            case "oschina":
                authRequest = new AuthOschinaRequest(AuthConfig.builder()
                                                             .clientId("")
                                                             .clientSecret("")
                                                             .redirectUri("http://localhost:8443/oauth/callback/oschina")
                                                             .build());
                break;
            case "qq":
                authRequest = new AuthQqRequest(AuthConfig.builder()
                                                        .clientId("")
                                                        .clientSecret("")
                                                        .redirectUri("http://localhost:8443/oauth/callback/qq")
                                                        .build());
                break;
            case "wechat_open":
                authRequest = new AuthWeChatOpenRequest(AuthConfig.builder()
                                                                .clientId("")
                                                                .clientSecret("")
                                                                .redirectUri("http://www.zhyd.me/oauth/callback/wechat")
                                                                .build());
                break;
            case "csdn":
                authRequest = new AuthCsdnRequest(AuthConfig.builder()
                                                          .clientId("")
                                                          .clientSecret("")
                                                          .redirectUri("http://dblog-web.zhyd.me/oauth/callback/csdn")
                                                          .build());
                break;
            case "taobao":
                authRequest = new AuthTaobaoRequest(AuthConfig.builder()
                                                            .clientId("")
                                                            .clientSecret("")
                                                            .redirectUri("http://dblog-web.zhyd.me/oauth/callback/taobao")
                                                            .build());
                break;
            case "google":
                authRequest = new AuthGoogleRequest(AuthConfig.builder()
                                                            .clientId("")
                                                            .clientSecret("")
                                                            .redirectUri("http://localhost:8443/oauth/callback/google")
                                                            .scopes(AuthScopeUtils.getScopes(AuthGoogleScope.USER_EMAIL, AuthGoogleScope.USER_PROFILE, AuthGoogleScope.USER_OPENID))
                                                            // 针对国外平台配置代理
                                                            .httpConfig(HttpConfig.builder()
                                                                                .timeout(15000)
                                                                                .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 10080)))
                                                                                .build())
                                                            .build());
                break;
            case "facebook":
                authRequest = new AuthFacebookRequest(AuthConfig.builder()
                                                              .clientId("")
                                                              .clientSecret("")
                                                              .redirectUri("https://justauth.cn/oauth/callback/facebook")
                                                              .scopes(AuthScopeUtils.getScopes(AuthFacebookScope.values()))
                                                              // 针对国外平台配置代理
                                                              .httpConfig(HttpConfig.builder()
                                                                                  .timeout(15000)
                                                                                  .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 10080)))
                                                                                  .build())
                                                              .build());
                break;
            case "douyin":
                authRequest = new AuthDouyinRequest(AuthConfig.builder()
                                                            .clientId("")
                                                            .clientSecret("")
                                                            .redirectUri("http://dblog-web.zhyd.me/oauth/callback/douyin")
                                                            .build());
                break;
            case "linkedin":
                authRequest = new AuthLinkedinRequest(AuthConfig.builder()
                                                              .clientId("")
                                                              .clientSecret("")
                                                              .redirectUri("http://localhost:8443/oauth/callback/linkedin")
                                                              .scopes(null)
                                                              .build());
                break;
            case "microsoft":
                authRequest = new AuthMicrosoftRequest(AuthConfig.builder()
                                                               .clientId("")
                                                               .clientSecret("")
                                                               .redirectUri("http://localhost:8443/oauth/callback/microsoft")
                                                               .scopes(Arrays.asList(
                                                                       AuthMicrosoftScope.USER_READ.getScope(),
                                                                       AuthMicrosoftScope.USER_READWRITE.getScope(),
                                                                       AuthMicrosoftScope.USER_READBASIC_ALL.getScope(),
                                                                       AuthMicrosoftScope.USER_READ_ALL.getScope(),
                                                                       AuthMicrosoftScope.USER_READWRITE_ALL.getScope(),
                                                                       AuthMicrosoftScope.USER_INVITE_ALL.getScope(),
                                                                       AuthMicrosoftScope.USER_EXPORT_ALL.getScope(),
                                                                       AuthMicrosoftScope.USER_MANAGEIDENTITIES_ALL.getScope(),
                                                                       AuthMicrosoftScope.FILES_READ.getScope()
                                                               ))
                                                               .build());
                break;
            case "mi":
                authRequest = new AuthMiRequest(AuthConfig.builder()
                                                        .clientId("")
                                                        .clientSecret("")
                                                        .redirectUri("http://dblog-web.zhyd.me/oauth/callback/mi")
                                                        .build());
                break;
            case "toutiao":
                authRequest = new AuthToutiaoRequest(AuthConfig.builder()
                                                             .clientId("")
                                                             .clientSecret("")
                                                             .redirectUri("http://dblog-web.zhyd.me/oauth/callback/toutiao")
                                                             .build());
                break;
            case "teambition":
                authRequest = new AuthTeambitionRequest(AuthConfig.builder()
                                                                .clientId("")
                                                                .clientSecret("")
                                                                .redirectUri("http://127.0.0.1:8443/oauth/callback/teambition")
                                                                .build());
                break;
            case "pinterest":
                authRequest = new AuthPinterestRequest(AuthConfig.builder()
                                                               .clientId("")
                                                               .clientSecret("")
                                                               .redirectUri("https://eadmin.innodev.com.cn/oauth/callback/pinterest")
                                                               // 针对国外平台配置代理
                                                               .httpConfig(HttpConfig.builder()
                                                                                   .timeout(15000)
                                                                                   .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 10080)))
                                                                                   .build())
                                                               .build());
                break;
            case "renren":
                authRequest = new AuthRenrenRequest(AuthConfig.builder()
                                                            .clientId("")
                                                            .clientSecret("")
                                                            .redirectUri("http://127.0.0.1:8443/oauth/callback/teambition")
                                                            .build());
                break;
            case "stack_overflow":
                authRequest = new AuthStackOverflowRequest(AuthConfig.builder()
                                                                   .clientId("")
                                                                   .clientSecret("((")
                                                                   .redirectUri("http://localhost:8443/oauth/callback/stack_overflow")
                                                                   .stackOverflowKey("")
                                                                   .build());
                break;
            case "huawei":
                authRequest = new AuthHuaweiRequest(AuthConfig.builder()
                                                            .clientId("")
                                                            .clientSecret("")
                                                            .redirectUri("http://127.0.0.1:8443/oauth/callback/huawei")
                                                            .scopes(Arrays.asList(
                                                                    AuthHuaweiScope.BASE_PROFILE.getScope(),
                                                                    AuthHuaweiScope.MOBILE_NUMBER.getScope(),
                                                                    AuthHuaweiScope.ACCOUNTLIST.getScope(),
                                                                    AuthHuaweiScope.SCOPE_DRIVE_FILE.getScope(),
                                                                    AuthHuaweiScope.SCOPE_DRIVE_APPDATA.getScope()
                                                            ))
                                                            .build());
                break;
            case "wechat_enterprise":
                authRequest = new AuthWeChatEnterpriseQrcodeRequest(AuthConfig.builder()
                                                                            .clientId("")
                                                                            .clientSecret("")
                                                                            .redirectUri("http://justauth.cn/oauth/callback/wechat_enterprise")
                                                                            .agentId("1000003")
                                                                            .build());
                break;
            case "kujiale":
                authRequest = new AuthKujialeRequest(AuthConfig.builder()
                                                             .clientId("")
                                                             .clientSecret("")
                                                             .redirectUri("http://dblog-web.zhyd.me/oauth/callback/kujiale")
                                                             .build());
                break;
            case "gitlab":
                authRequest = new AuthGitlabRequest(AuthConfig.builder()
                                                            .clientId("")
                                                            .clientSecret("")
                                                            .redirectUri("http://localhost:8443/oauth/callback/gitlab")
                                                            .scopes(AuthScopeUtils.getScopes(AuthGitlabScope.values()))
                                                            .build());
                break;
            case "meituan":
                authRequest = new AuthMeituanRequest(AuthConfig.builder()
                                                             .clientId("")
                                                             .clientSecret("")
                                                             .redirectUri("http://localhost:8443/oauth/callback/meituan")
                                                             .build());
                break;
            case "eleme":
                authRequest = new AuthElemeRequest(AuthConfig.builder()
                                                           .clientId("")
                                                           .clientSecret("")
                                                           .redirectUri("http://dblog-web.zhyd.me/oauth/callback/eleme")
                                                           .build());
                break;
            case "twitter":
                authRequest = new AuthTwitterRequest(AuthConfig.builder()
                                                             .clientId("")
                                                             .clientSecret("")
                                                             .redirectUri("https://threelogin.31huiyi.com/oauth/callback/twitter")
                                                             // 针对国外平台配置代理
                                                             .httpConfig(HttpConfig.builder()
                                                                                 .timeout(15000)
                                                                                 .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 10080)))
                                                                                 .build())
                                                             .build());
                break;
            case "wechat_mp":
                authRequest = new AuthWeChatMpRequest(AuthConfig.builder()
                                                              .clientId("")
                                                              .clientSecret("")
                                                              .redirectUri("")
                                                              .build());
                break;
            case "aliyun":
                authRequest = new AuthAliyunRequest(AuthConfig.builder()
                                                            .clientId("")
                                                            .clientSecret("")
                                                            .redirectUri("http://localhost:8443/oauth/callback/aliyun")
                                                            .build());
                break;
            case "xmly":
                authRequest = new AuthXmlyRequest(AuthConfig.builder()
                                                          .clientId("")
                                                          .clientSecret("")
                                                          .redirectUri("http://localhost:8443/oauth/callback/xmly")
                                                          .build());
                break;
            case "feishu":
                authRequest = new AuthFeishuRequest(AuthConfig.builder()
                                                            .clientId("")
                                                            .clientSecret("")
                                                            .redirectUri("http://localhost:8443/oauth/callback/feishu")
                                                            .build());
                break;
            default:
                break;
        }
        if (null == authRequest) {
            throw new AuthException("未获取到有效的Auth配置");
        }
        return authRequest;
    }

}
